;/*
    This file is part of Darwin.

    Darwin is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Foobar is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    
    Darwin uses GALib
    Copyright (c) 1995-1996 Massachusetts Institute of Technology (MIT)
    Copyright (c) 1996-2005 Matthew Wall
    All rights reserved.
    
    Darwin uses ConfigFile
    Copyright (c) 2004 Richard J. Wagner
     
    Darwin, a Genetic Algorithm to solve Timetabling problem
    Copyright (c) 2006 Christian S. Perone
*/  

#include "main.h"

void Connect_MySQL(void)
{
     cout << "Connecting to MySQL at " << g_options.mysql_username << "@"
          << g_options.mysql_hostname << "/" << g_options.mysql_database << " ...";
     cout.flush();

     /// Connect to MySQL using config. constants
     if(!g_connection.connect(  g_options.mysql_database.c_str(),
                                g_options.mysql_hostname.c_str(),
                                g_options.mysql_username.c_str(),
                                g_options.mysql_password.c_str()))
     {
          cout << "Error while connecting: " << g_connection.error() << endl;
          exit(errors::ERROR_CONNECT);
     }
     
     cout << " OK!" << endl;
     cout.flush();
     return;
}

int main(int argc, char **argv)
{
     cout << endl << "Darwin - A TimeTabling Genetic Algorithm" << endl << endl;
     cout << "Author: Christian S. Perone" << endl;

     cout << "Loading configuration...";
     cout.flush();
     // Parse the config file
     g_options.Parse();
     cout << " OK!" << endl;
     cout.flush();

     if(!g_options.ga_random_seed) GARandomSeed();
     else GARandomSeed(g_options.ga_random_seed);

     // Connect to MySQL
     Connect_MySQL();

     // teste dos mappings pra tabelas
     cout << "Loading data to memory...";
     cout.flush();
     map_professordisciplina.LoadData();
     map_disciplina.LoadData();
     map_oferecimento.LoadData();
     map_curso.LoadData();
     map_professor.LoadData();
     map_disponibilidade.LoadData();
     map_diasemana.LoadData();     
     cout << " OK!" << endl;
     cout.flush();
     TimeGenome genome(g_options.timetabling_niveis);
     GASimpleGA ga(genome);
     GARouletteWheelSelector selector;
     ga.selector(selector);
     
     ga.populationSize(g_options.ga_popsize);
     ga.nGenerations(g_options.ga_generations);
     ga.pMutation(g_options.ga_mutation);
     ga.pCrossover(g_options.ga_crossover);
     ga.nConvergence(g_options.ga_convergence);
     
     
     
     ga.initialize();
     cout << endl << "Evolving..." << endl;
     cout.flush();
     while(!ga.done())
     {
          if(ga.generation() % g_options.ga_showstats == 0)
          {
               cout << "Generation [" << ga.generation() << "]" << endl;
               cout << "Mutations    = " << ga.statistics().mutations() << endl;
               cout << "Crossovers   = " << ga.statistics().crossovers() << endl;
               cout << "nConvergence = " << ga.statistics().nConvergence() << endl;
               cout << "Convergence  = " << ga.statistics().convergence() << endl;
               cout << "Best Score   = " << ga.statistics().bestIndividual().score() << endl;
               cout << "Max Ever     = " << ga.statistics().maxEver() << endl;
               cout << "Min Ever     = " << ga.statistics().minEver() << endl;
               cout << "------------------------------------" << endl;
          }
          ga.step();
     }
     cout << "Ok !" << endl;
     
        
     TimeGenome &best = (TimeGenome &)ga.statistics().bestIndividual();
     
     for(int i=0; i<best.GetNiveis(); i++)
     {
          cout << "---- Nivel: " << i << endl;
          for(uint x=0; x<best.GetNivelList(i).size(); x+=2)
          {
               cout << "x[" << x << "] = " << best.GetNivelList(i)[x] << " x[" << x+1 << "] = " << best.GetNivelList(i)[x+1] << endl;
               
          }
     }


     mysqlpp::Query query_db_clear = g_connection.query();
     mysqlpp::Query query_db_flush = g_connection.query();


     cout << endl << "Flush best individual to Database...";
     cout.flush();
     query_db_clear << "DELETE FROM TIMESLOTTURMA";
     query_db_clear.execute();
     query_db_clear.reset();
     
     for(int i=0; i<best.GetNiveis(); i++)
     {
          for(uint x=0; x<best.GetNivelList(i).size(); x++)
          {
               query_db_flush << "INSERT INTO TIMESLOTTURMA VALUES (" \
                              << g_options.timetabling_anosemestre \
                              << "," << x << ",1," << best.GetNivelList(i)[x] << "," << i+1 << ")";

               query_db_flush.execute();
               query_db_flush.reset();
          }
     }

     g_connection.close();

     cout << " OK!" << endl;

     cout << endl << endl;
     return 0;
}
